package edu.indiana.d2i.registry;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.wso2.carbon.governance.api.endpoints.dataobjects.Endpoint;
import org.wso2.carbon.governance.api.services.ServiceManager;
import org.wso2.carbon.governance.api.services.dataobjects.Service;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.ws.client.registry.WSRegistryServiceClient;

import edu.indiana.d2i.util.Utilities;

/**
 * 
 */
public class RegistryClient {
	private static ConfigurationContext configContext = null;

	// properties for connection
	private String axis2Repo = "";
	private String axis2Conf = "";
	private String keyStore = "";
	private String username = "admin";
	private String password = "admin";
	private String serverURL = "https://localhost:9443/services/";
	// private String serverURL =
	// "https://coffeetree.cs.indiana.edu:9443/services/";
	// properties for resources' locations
	private String scriptLocation = "";
	private String collectionLocation = "";
	private String serviceLocation = "";

	private Map<String, String> scriptNameMap = new HashMap<String, String>();
	private final String CONF_FILE = "config.properties";
	private final String DELIMINATOR = ",\n";

	private Registry registry = null;

	private void readProperties() {
		Properties prop = new Properties();
		try {
			prop.load(new FileInputStream(this.CONF_FILE));

			// connection properties
			keyStore = prop.getProperty("key_store");
			axis2Repo = prop.getProperty("axis2_repo");
			axis2Conf = prop.getProperty("axis2_conf");
			username = prop.getProperty("username");
			password = prop.getProperty("password");
			serverURL = prop.getProperty("serverurl");

			// resources locations
			scriptLocation = prop.getProperty("script");
			collectionLocation = prop.getProperty("collection");
			serviceLocation = prop.getProperty("services");
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * hard code to parse the XML  
	 */
	private String getServiceURI(String serviceName, String port) {
		// try {
		// Registry governanceRegistry = GovernanceUtils
		// .getGovernanceUserRegistry(this.registry, username);
		// ServiceManager serviceManager = new ServiceManager(
		// governanceRegistry);
		// Service[] services = serviceManager.getAllServices();
		// for (Service service : services) {
		// if (service.getQName().getLocalPart().equals(serviceName)) {
		// Endpoint[] endpoints = service.getAttachedEndpoints();
		// // for (Endpoint endpoint : endpoints) {
		// // if (endpoint.getUrl().contains(port)) return endpoint.getUrl();
		// // }
		// return endpoints[0].getUrl(); // ??
		// }
		// }
		// } catch (RegistryException e) {
		// e.printStackTrace();
		// }
		//
		// return null;

		try {
			Resource serviceResource = this.registry.get(this.serviceLocation
					+ "/" + serviceName);
			
			String url = null;
			boolean bHasService = false;
			InputStream stream = new ByteArrayInputStream((byte[])serviceResource.getContent());
			XMLInputFactory factory = XMLInputFactory.newInstance();
			XMLStreamReader parser = factory.createXMLStreamReader(stream);
			while (parser.hasNext()) {
				int event = parser.next();
				switch (event) {
				case XMLStreamConstants.START_ELEMENT:
					if (parser.getLocalName().equals("name")) {
						if (parser.getElementText().equals(serviceName)) {
							bHasService = true;
						}
					}
					else if (bHasService) {
						if (parser.getLocalName().equals("entry")) {
							url = parser.getElementText();
						}
					}
					break;
				}
			}
			
			if (url != null) {
				if (!url.equals("")) {
					return url.substring(url.indexOf(":")+1);
				}
			}
		} catch (RegistryException e) {
			e.printStackTrace();
		} catch (XMLStreamException e) {
			e.printStackTrace();
		}
//		return new String((byte[])serviceResource.getContent());
		return null;
	}

	private WSRegistryServiceClient initialize() throws Exception {
		System.setProperty("javax.net.ssl.trustStore", keyStore);
		System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
		System.setProperty("javax.net.ssl.trustStoreType", "JKS");

		configContext = ConfigurationContextFactory
				.createConfigurationContextFromFileSystem(axis2Repo, axis2Conf);
		return new WSRegistryServiceClient(serverURL, username, password,
				configContext);
	}

	public RegistryClient() {
		try {
			// read properties
			readProperties();

			// initialize the registry
			this.registry = initialize();

			// set the application names map
			scriptNameMap.put("simplescript", "simplescript.jar");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String getScriptFile(String scriptName) {
		try {
			// get file name
			String filename = this.scriptNameMap.get(scriptName);
			Resource scriptResource = this.registry.get(this.scriptLocation
					+ "/simplescript.jar");

			// download the file to local disk
			Utilities.downloadFile(scriptResource, filename);

			// byte[] bytes = new byte[1024];
			// int read = 0;
			// InputStream contentStream = scriptResource.getContentStream();
			// while ((read = contentStream.read(bytes)) != -1) {
			// bos.write(bytes);
			// }
			// contentStream.close();
			// bos.close();

			return filename;
		} catch (RegistryException e) {
			e.printStackTrace();
		}

		return null;
	}

	public String getSolrIndexServiceURI(String serviceName) {
		return getServiceURI(serviceName, "8888");
	}

	public String getRepositoryURI(String serviceName) {
		return getServiceURI(serviceName, "9160");
	}

	/**
	 * The format of IUCollection.csv should be volumeID1,\n volumeID2,\n ...
	 */
	public List<String> getVolumeIDsFromCollection(String collectionName) {
		try {
			// download the csv file
			Resource volumeIDsResource = this.registry
					.get(this.collectionLocation + "/IUCollection.csv");
			// save it in local disk ??
			// Utilities.downloadFile(volumeIDsResource, "volumn.csv");

			List<String> volumeIDs = new ArrayList<String>();
			String[] splits = new String(
					(byte[]) volumeIDsResource.getContent())
					.split(this.DELIMINATOR);
			for (String str : splits) {
				// System.out.println(str);
				volumeIDs.add(str);
			}
			return volumeIDs;
		} catch (RegistryException e) {
			e.printStackTrace();
		}

		return null;
	}

	/* test driver */
	public static void main(String[] args) throws Exception {
		RegistryClient client = new RegistryClient();
		List<String> volumeIDs = client
				.getVolumeIDsFromCollection("IU collection");
		for (String volume : volumeIDs) {
			System.out.println(volume);
		}
		System.out.println("-------------------------------------------------");

		// String file = client.getScriptFile("simplescript");
		// System.out.println(file);
		// System.out.println("-------------------------------------------------");

		String uri = client.getSolrIndexServiceURI("htrc-apache-solr-search");
		System.out.println(uri);
		System.out.println("-------------------------------------------------");

		String repoURI = client.getRepositoryURI("htrc-cassandra-repository");
		System.out.println(repoURI);
	}
}
